/**
 * Copyright 2005 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.edi.client.param;

import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;

import com.edi.Constant;
import com.edi.Kola;
import com.edi.client.plugin.PluginResult;
import com.edi.db.manager.DBManager;
import com.edi.db.table.ColumnCell;
import com.edi.db.table.RowEntity;
import com.edi.db.table.TableEntity;
import com.edi.db.type.StringType;
import com.edi.pubsub.EdiService;

/**
 * FixTable，对应协议中的FixTable元素，用来做表的混合
 * 
 * @author 红木
 * 
 */
public class FixTable {
	private static final Log log = LogFactory.getLog(FixTable.class);
	private Element fiexTableE;
	private String associateSource;
	private String associateTarget;
	private HashMap<String, FixMap> fieldMaps = new HashMap<String, FixMap>();
	private String eql;
	private FixService fixService;

	public FixTable(Element fixTableE) {
		this.fiexTableE = fixTableE;

		Element associatFieldE = fixTableE.element("associateField");
		this.associateSource = associatFieldE.attributeValue("source");
		this.associateTarget = associatFieldE.attributeValue("target");
		List<Element> mapsE = fixTableE.elements("map");
		for (Element mapE : mapsE) {
			fieldMaps.put(mapE.attributeValue("mapField"), new FixMap(mapE));
		}
		Element eqlE = fixTableE.element("eql");
		Element serviceE = fixTableE.element("service");

		if (serviceE != null) {
			fixService = new FixService(fixTableE.element("service"));
		}
	}

	/**
	 * 混合表内容
	 * 
	 * @param originalTalble
	 */
	public void toFix(TableEntity originalTalble) throws Exception {
		if (eql != null) {
			fixByEql(originalTalble);
		} else if (fixService != null) {
			fixByService(originalTalble);
		}
	}

	/**
	 * 
	 * @param tableEntity
	 */
	private void fixByEql(TableEntity tableEntity) throws Exception {
		if (tableEntity.getRows().size() == 0)
			return;
		StringBuffer condition = new StringBuffer();
		associateSource = associateSource.toLowerCase();
		associateTarget = associateTarget.toLowerCase();
		for (RowEntity row : tableEntity.getRows()) {

			Object obj = row.getValue(associateSource);
			int sqlType = row.getColumnCells().get(associateSource)
					.getFieldType().sqlType();
			if (obj == null)
				continue;
			if (sqlType == Types.VARCHAR)
				condition.append("'" + row.getValue(associateSource) + "'")
						.append(",");

			else
				condition.append(row.getValue(associateSource)).append(",");
		}
		if (condition.lastIndexOf(",") == condition.length() - 1)
			condition.deleteCharAt(condition.length() - 1);
		if (condition.length() == 0)
			return;
		log.debug(" condition =" + condition.toString());
		if (eql.contains(" where "))
			eql = eql + " and " + associateTarget + " in ("
					+ condition.toString() + ")";
		else
			eql = eql + " where " + associateTarget + " in ("
					+ condition.toString() + ")";
		log.debug(" after condition eql =" + eql);
		//		EdiServiceParam<PreparedEql> serviceParam = new EdiServiceParam<PreparedEql>();
		//		PreparedEql preparedEql = new PreparedEql();
		//		preparedEql.eql = eql;
		//		serviceParam.setServiceParam(preparedEql);
		//		serviceParam.setRemote(false);
		//		serviceParam.appName = appName;
		//		serviceParam.setServiceName("EdiServer.serviceQueryEql");
		//		EdiService service = EDIServer.getEDIServerInstance()
		//				.getServiceManager().getService("EdiServer.serviceQueryEql");
		//		PluginResult result = service.execute(serviceParam);

		//		log.debug(" result = null " + (result == null));

		DBManager dbManager = new DBManager(Constant.SERVER_APPNAME);
		TableEntity result = dbManager.queryEql(eql);
		//		
		//		Object table = result.getResult();
		//		if (table instanceof TableEntity)
		rebuildTable(tableEntity, result);
	}

	/**
	 * 
	 * @param tableEntity
	 */
	private void fixByService(TableEntity tableEntity) throws Exception {
		log.debug(" enter  fixByService=");
		EdiClientParam param = new EdiServiceParam();
		param.setEdiPara(fixService.getParamsE());
		log
				.debug("fixService.getParamsE() ="
						+ fixService.getParamsE().asXML());
		Element element = fixService.getParamsE().element("serviceName");
		log.debug("serviceName =" + element.getText());
		param.setServiceName(element.getText());
		EdiService service = Kola.getServiceManager().getService(
				fixService.serviceName);
		PluginResult result = service.execute(param);
		Object table = result.getResult();
		boolean isTable = table instanceof TableEntity;
		log.debug(" isTable =" + isTable);
		if (isTable)
			rebuildTable(tableEntity, (TableEntity) table);
		log.debug(" end  fixByService=");
	}

	/**
	 * 表替换表 用于 eql查询和服务查询
	 * 
	 * @param sourceTable
	 * @param targetTable
	 */
	private void rebuildTable(TableEntity sourceTable, TableEntity targetTable) {
		log.debug(" enter reBuildTable ");
		for (RowEntity row : sourceTable.getRows()) {
			Object associateSValue = row.getValue(associateSource);
			log.debug("associateSValue =" + associateSValue);
			for (String key : fieldMaps.keySet()) {
				log.debug(" key =" + key);
				if (StringUtils.isBlank(key))
					continue;
				boolean isNull = row.getCell(key) == null;
				log.debug("isNull =" + isNull);
				log.debug("row  =" + row.getColumnCells().size());
				if (isNull) {
					//添加新单元格
					ColumnCell newCell = new ColumnCell();
					newCell.setFieldName(key);
					newCell.setFieldType(new StringType());
					row.addCell(key, newCell);

					//为新cell赋值
					List<RowEntity> targetRows = targetTable.getRows();
					for (RowEntity targetRow : targetRows) {
						Object associateTValue = targetRow
								.getValue(associateTarget);
						if (StringUtils.equals(associateSValue.toString(),
								associateTValue.toString())) {
							FixMap fixMap = fieldMaps.get(newCell
									.getFieldName());
							newCell.setFieldValue(targetRow
									.getValue(fixMap.targetField));
						}
					}
				}
				log.debug("after row  =" + row.getColumnCells().size());
			}
			//			for (ColumnCell cell : row.getColumnCells().values()) {
			//				String cellName = cell.getFieldName();
			//				FixMap fixMap = fieldMaps.get(cellName);
			//				if (fixMap == null)
			//					continue;
			//				String targetName = fixMap.targetField;
			//				log.debug(" cellName =" + cellName);
			//				log.debug(" targetName =" + targetName);
			//				if (targetName != null) {
			//					if (cell.getFieldType() == null) //非新添加单元格，替换名称
			//						//cell.setFieldName(targetName); //替换表格单元名称 
			////					else
			//						cell.setFieldEntity(targetTable.getFieldEntitys().get(
			//								targetName));
			//					//替换单元格值 
			//					Iterator<RowEntity> innerRowIt = targetTable.getRows()
			//							.iterator();
			//					while (innerRowIt.hasNext()) {
			//						RowEntity innerRow = innerRowIt.next();
			//						Object associateTValue = innerRow
			//								.getValue(associateTarget);
			//						log.debug("associateTValue = " + associateTValue);
			//						boolean flg = associateTValue.equals(associateSValue);
			//						log.debug("associateTValue.equals(associateSValue) ="
			//								+ flg);
			//						if (flg) {
			//							log.debug(" 替换列 ");
			//							log.debug(" value ="
			//									+ innerRow.getCell(targetName)
			//											.getFieldValue());
			//							cell.setFieldValue(innerRow.getCell(targetName)
			//									.getFieldValue());
			//							cell.setFieldType(innerRow.getCell(targetName)
			//									.getFieldType());
			//						}
			//					}
			//				}
			//			}
		}
		log.debug(" end reBuildTable ");
	}

	class FixService {
		private String serviceName;
		private List<String> paramValues;
		private Element paramsE;

		public FixService(Element serviceE) {
			paramValues = new ArrayList<String>();
			this.serviceName = serviceE.elementText("serviceName");
			this.paramsE = serviceE;
			List<Element> paramsE = serviceE.element("parameters").elements(
					"param");
			for (Element paramE : paramsE) {
				paramValues.add(paramE.getText());
			}
		}

		public Element getParamsE() {
			return this.paramsE;
		}
	}

	class FixMap {
		private String mapField;
		private String targetField;

		//		private boolean addField;

		public FixMap(Element mapE) {
			this.mapField = mapE.attributeValue("mapField");
			this.targetField = mapE.attributeValue("targetField");
			//			this.addField = mapE.attributeValue("add").equals("true")?true:false;
		}
	}

}
